﻿using Yxinmt.Interface;
using Yxinmt.Utility;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;


namespace Yxinmt.Controls
{
    public class TextBox : BaseControl, IControl
    {
        private System.Windows.Controls.TextBox _TextBox { get; set; }
        string _Placeholder { get; set; }

        public TextBox(Dictionary<string, object> property, IComponent component)
        {
            Property = property;
            _Component = component;
            _TextBox = new System.Windows.Controls.TextBox();
            this.Element = _TextBox;

            InitSet();
            SetProperty();
            this.SetControlProperty();
        }

        string _DataType { get; set; }

        private void SetProperty()
        {
            this.SetDefaultValue("IsDefaultValue", false);
            _DataType = Property.GetStringValue("DataType");

            _NumberList = InitNumberKeyList();

            bool blDefaultValue = !Property.ContainsKey("IsDefaultValue") ? true : Property.GetValue<bool>("IsDefaultValue");

            if (blDefaultValue)
            {
                this.SetDefaultValue("ControlMarginTop", 5);
                this.SetDefaultValue("ControlMarginLeft", 5);
                this.SetDefaultValue("IsEdit", true);
                this.SetDefaultValue("MaxLength", 50);
                this.SetDefaultValue("IsNullable", true);
                this.SetDefaultValue("AcceptsTab", true);
            }

            _IsBlur = Property.GetValue<bool>("IsBlur");
            _IsReadOnly = Property.GetValue<bool>("IsReadOnly");
        }

        protected override void SetProperty(string name, object value)
        {
            System.Windows.Controls.TextBox c = _TextBox;
            switch (name)
            {
                case "name": c.Name = string.Concat("txt_", (string)value); break;
                case "ControlWidth": c.Width = Convert.ToDouble(value); break;
                case "Width": c.Width = Convert.ToDouble(value); break;
                case "Height": c.Height = Convert.ToDouble(value); break;
                case "MaxLength": c.MaxLength = Convert.ToInt32(value); break;
                case "Text": c.Text = (string)value; break;
                case "Placeholder": c.Text = (string)value; _Placeholder = c.Text; break;
                case "TextAlign": SetTextAlign((string)value); break;
                case "ControlAlign": SetControlAlign((string)value); break;
                case "Padding": c.Padding = this.GetThickness((string)value); break;
                case "Visible": SetVisible(Convert.ToBoolean(value)); break;
                case "Dock": System.Windows.Controls.DockPanel.SetDock(c, this.GetDock((string)value)); break;
                case "Margin": c.Margin = this.GetThickness((string)value); break;
                case "BackColor": c.Background = GetColor((string)value); break;
                case "BorderColor": c.BorderBrush = GetColor((string)value); break;
                case "BorderThickness": c.BorderThickness = this.GetThickness((string)value); break;
                case "TextWrapping": c.TextWrapping = GetTextWrapping((string)value); break;
                case "ZIndex": SetZIndex(Convert.ToInt32(value)); break;
                case "CanvasLocation": SetCanvasLocation((string)value); break;
                case "CanvasZIndex": SetCanvasZIndex(Convert.ToInt32(value)); break;
                case "Value": SetValue(value); break;
                case "AcceptsReturn": c.AcceptsReturn = (bool)value; break;
                case "AcceptsTab": c.AcceptsTab = (bool)value; break;
                case "IsReadOnly": c.IsReadOnly = (bool)value; break;
                case "Cursor": c.Cursor = GetCursor((string)value); break;
            }
        }

        public Action<object, EventArgs, IControl> TextClickAction { get; set; }
        public Action<object, EventArgs, IControl> TextDoubleClickAction { get; set; }

        public override void EventLoad()
        {
            base.EventLoad();

            _TextBox.GotFocus += _TextBox_GotFocus;
            if (_IsBlur || !_TextBox.IsReadOnly) _TextBox.LostFocus += _TextBox_LostFocus;

            _TextBox.KeyDown += _TextBox_KeyDown;
            _TextBox.KeyUp += _TextBox_KeyUp;
            _TextBox.TextChanged += _TextBox_TextChanged;


            bool isClick = Property.GetValue<bool>("IsClick");
            bool isDoubleClick = Property.GetValue<bool>("IsDoubleClick");

            if (isClick || isDoubleClick)
            {
                ClickAction = (sender, e, ctl) =>
                {
                    if (_DataGridViewControls != null) _DataGridViewControls.DataGridView.EventInvoke(sender, e, this, "RowClick");
                    if (TextClickAction != null) TextClickAction(sender, e, this);
                    else this._Window.EventInvoke(sender, e, this);
                };

                DoubleClickAction = (sender, e, ctl) =>
                {
                    if (_DataGridViewControls != null) _DataGridViewControls.DataGridView.EventInvoke(sender, e, this, "RowDoubleClick");
                    if (TextDoubleClickAction != null) TextDoubleClickAction(sender, e, this);
                    else this._Window.DoubleEventInvoke(sender, e, this);
                };

                bool isMouseDown = Property.GetValue<bool>("IsMouseDown");
                bool isMouseUp = Property.GetValue<bool>("IsMouseUp");

                if (isMouseDown)
                {
                    MouseDownAction = (sender, e, ctl) =>
                    {
                        if (_DataGridViewControls != null) _DataGridViewControls.DataGridView.EventInvoke(sender, e, this, "RowMouseDown");
                    };
                }

                if (isMouseUp)
                {
                    MouseUpAction = (sender, e, ctl) =>
                    {
                        if (_DataGridViewControls != null) _DataGridViewControls.DataGridView.EventInvoke(sender, e, this, "RowMouseUp");
                    };
                }

                BindPreviewClick(isClick, isDoubleClick);
            }
        }

        public void SetLostFocus()
        {
            _TextBox.Focusable = false;
        }

        void _TextBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
        {
            if (_TextBox.IsReadOnly) return;

            try
            {
               if (TextChanged != null) TextChanged(_TextBox.Text);
            }
            catch (Exception ex)
            {
                LoggerProxy.Exception(Name, "_TextBox_TextChanged", ex);
            }
        }

        public Action<string> TextChanged { get; set; }

        public Action<IControl> EnterAction { get; set; }

        public bool IsReadonly()
        {
            return _TextBox.IsReadOnly;
        }

        void _TextBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (_TextBox.IsReadOnly) return;

            try
            {
                if (e.Key == System.Windows.Input.Key.Enter && EnterAction != null) EnterAction(this);
            }
            catch (Exception ex)
            {
                LoggerProxy.Exception(Name, "_TextBox_KeyUp", ex);
            }
        }

        List<System.Windows.Input.Key> _NumberList { get; set; }

        void _TextBox_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (_TextBox.IsReadOnly) return;

            try
            {
                if (_DataType == "int")
                {
                    if (!_NumberList.Exists(w => w == e.Key)) { e.Handled = true; return; }
                    else if (string.IsNullOrEmpty((string)GetValue())
                        && (e.Key == System.Windows.Input.Key.D0 || e.Key == System.Windows.Input.Key.NumPad0)) { e.Handled = true; return; }
                }
            }
            catch (Exception ex)
            {
                LoggerProxy.Exception(Name, "_TextBox_KeyDown", ex);
            }
        }

        bool _IsBlur { get; set; }
        bool _IsReadOnly { get; set; }

        void _TextBox_LostFocus(object sender, System.Windows.RoutedEventArgs e)
        {
            try
            {
                if (_IsReadOnly) SetEdit(false);

                if (_DataType == "int")
                {
                    int i = 0;
                    string value = (string)GetValue();

                    if (!string.IsNullOrEmpty(value) && !int.TryParse(value, out i))
                    {
                        this._Window.Alert("数据类型不正确，请输入自然数！", () =>
                        {
                            Task.Run(() => { Thread.Sleep(100); _TextBox.Dispatcher.Invoke(() => _TextBox.Focus()); });
                        });
                    }
                }

                if (LostFocus != null) LostFocus(this);
            }
            catch (Exception ex)
            {
                LoggerProxy.Exception(Name, "_TextBox_LostFocus", ex);
            }
        }

        bool _IsEdit { get; set; }

        public Action<IControl> GotFocus { get; set; }
        public Action<IControl> LostFocus { get; set; }

        void _TextBox_GotFocus(object sender, System.Windows.RoutedEventArgs e)
        {
            try
            {
                if (!string.IsNullOrEmpty(_Placeholder) && _TextBox.Text == _Placeholder) { _TextBox.Text = string.Empty; _IsEdit = true; }

                if (GotFocus != null) GotFocus(this);
            }
            catch (Exception ex)
            {
                LoggerProxy.Exception(Name, "_TextBox_GotFocus", ex);
            }
        }

        string _SelectText { get; set; }

        public void SetFocus()
        {
            if (!_TextBox.IsFocused) _TextBox.Focus();
        }

        public void SetEdit(bool blEdit)
        {
            if (_TextBox.IsReadOnly != blEdit) return;

            _IsReadOnly = !blEdit;
            _TextBox.IsReadOnly = !blEdit;
            _TextBox.Cursor = GetCursor(blEdit ? "IBeam" : "Arrow");
            if (blEdit) { _TextBox.SelectAll(); _SelectText = _TextBox.Text; }
            else if (string.IsNullOrEmpty((string)GetValue())) _TextBox.Text = _SelectText;
        }

        public override bool ValidateNullable(out string message)
        {
            message = string.Empty;
            bool isNullable = this.Property.GetValue<bool>("IsNullable");
            string label = this.Property.GetStringValue("Label");
            label = label ?? string.Empty;
            label = label.TrimEnd(new char[] { '：', ':' });
            if (!isNullable)
            {
                if (string.IsNullOrEmpty((string)this.GetValue()))
                {
                    message = string.Format("{0}，不能为空！", label);
                    this._TextBox.Focus();
                    return false;
                }
            }

            return true;
        }

        public override object GetValue()
        {
            string value = this._TextBox.Text.Trim();
            if (!_IsEdit && value == _Placeholder) value = string.Empty;
            return value;
        }

        public override void SetValue(object value)
        {
            string text = GetValueText(value);
            if (string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(_Placeholder)) text = _Placeholder;
            _TextBox.Text = text;
        }

        public void SetFontColor(string color)
        {
            if (_Control == null) return;

            if (!string.IsNullOrEmpty(color))
            {
                this._Control.Foreground = new System.Windows.Media.SolidColorBrush(Utility.Common.GetColor(color));
            }
        }
    }
}
